using System;
using System.Xml;
using System.Threading;
using System.Collections.Generic;

namespace RealDolmen.SharePoint.ListFeatures.Elements
{
    public abstract class ListFeatureElement : ListFeatureObject
    {
        #region Abstract Methods
        public abstract void Activate(ListFeature listFeature);
        public abstract void Deactivate(ListFeature listFeature);
        public abstract bool Customizable { get; }
        #endregion // Abstract Methods

        #region Public Properties
        private ListFeatureElementsFile elementsFile;
        private XmlNode xmlDefinition;

        public ListFeatureElementsFile ElementsFile
        {
            get
            {
                return elementsFile;
            }
            set
            {
                elementsFile = value;
            }
        }
        
        public XmlNode XmlDefinition
        {
            get
            {
                return xmlDefinition;
            }
            internal set
            {
                xmlDefinition = value;
            }
        }
        private static Dictionary<string, Type> s_dictElementTypes;
        public static Dictionary<string, Type> ElementTypesDict
        {
            get
            {
                EnsureElementTypeDict();
                return s_dictElementTypes;
            }
        }
        #endregion // Public Properties

        #region Overrides
        public override string GetDefaultElement(object name)
        {
            XmlElement element = XmlDefinition[name.ToString()];
            if(element != null)
                return element.InnerText;
            else
                return null;
        }

        public string GetDefaultAttribute(object name)
        {
            return GetDefaultAttribute(name.ToString());
        }

        public string GetDefaultAttribute(string name)
        {
            XmlAttribute xmlAttribute =
                XmlDefinition.Attributes[name];
            if (xmlAttribute == null)
                return null;
            else
                return xmlAttribute.Value;
        }

        public string GetDefaultAttribute(object name, string defaultString)
        {
            return GetDefaultAttribute(name.ToString(), defaultString);
        }

        public string GetDefaultAttribute(string name, string defaultString)
        {
            string val = GetDefaultAttribute(name);
            if (val == null)
                val = defaultString;
            return val;
        }
        #endregion // Overrides

        #region Statics
        public static ListFeatureElement CreateAppropriateElementType(XmlNode xnElementDefinition, ListFeatureDefinition featdef, ListFeatureElementsFile elementsFile)
        {
            ListFeatureElement element = null;
            Dictionary<string, Type> elementTypesDict = ElementTypesDict;
            if (elementTypesDict.ContainsKey(xnElementDefinition.Name))
            {
                Type type = elementTypesDict[xnElementDefinition.Name];
                element = (ListFeatureElement)Activator.CreateInstance(type);
                element.XmlDefinition = xnElementDefinition;
                element.FeatureDefinition = featdef;
                element.ElementsFile = elementsFile;
            }
            return element;
        }

        public static ListFeatureElement CreateAppropriateElementType(XmlNode xnElementDefinition, ListFeatureDefinition featureDefinition, ListFeatureElementsFile elementsFile, ListFeature feature)
        {
            ListFeatureElement element = CreateAppropriateElementType(xnElementDefinition, featureDefinition, elementsFile);
            if (element != null)
            {
                element.Feature = feature;
            }
            return element;
        }

        private static void EnsureElementTypeDict()
        {
            if (s_dictElementTypes == null)
            {
                Dictionary<string, Type> dictionary = new Dictionary<string, Type>();
                dictionary.Add(ListFeatureTimerJobElement.RootTag, typeof(ListFeatureTimerJobElement));
                dictionary.Add(ListFeatureEventsElement.RootTag, typeof(ListFeatureEventsElement));
                dictionary.Add(ListFeatureCustomActionElement.RootTag, typeof(ListFeatureCustomActionElement));
                Interlocked.CompareExchange<Dictionary<string, Type>>(ref s_dictElementTypes, dictionary, null);
            }
        } 
        #endregion // Statics
    }
}
